package maping;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Set;
import java.util.TreeMap;

public final class OurPolygon {

    private int minY;
    private int maxY;
    private TreeMap< Integer, ArrayList<OurNode>> edgeTable = new TreeMap< Integer, ArrayList<OurNode>>();
    private ArrayList<OurPoint> points;


    /*
     * OurPolygon recibe un arreglo de n puntos, se asume que el punto i y el punto (i+1)%n forman una arista
     */

    public ArrayList<OurPoint> getPoints() {
        return points;
    }


    public int[] getMaxYPoint(){
        int values[]= new int [4];
        //maximo en X
        values[0]=Integer.MIN_VALUE;
        //maximo en Y
        values[1]=Integer.MIN_VALUE;
        //minimo en X
        values[2]=Integer.MAX_VALUE;
        //minimo en Y
        values[3]=Integer.MAX_VALUE;
        for(OurPoint p: points){
            if(values[0]<p.getX()){
                values[0]=p.getX();
            }
            if(values[1]<p.getY()){
                values[1]=p.getY();
            }
            if(values[2]>p.getX()){
                values[2]=p.getX();
            }
            if(values[3]>p.getY()){
                values[3]=p.getY();
            }
        }
        return values;
    }

    public TreeMap<Integer, ArrayList<OurNode>> getEdgeTable() {
        return edgeTable;
    }

    public int getMaxY() {
        return this.maxY;
    }

    public int getMinY() {
        return this.minY;
    }

    public void setEdgeTable(TreeMap<Integer, ArrayList<OurNode>> edgeTable) {
        this.edgeTable = edgeTable;
    }

    public OurPolygon(ArrayList<OurPoint> points) {
        this.points = points;
        OurPoint a, b, pMax, pMin;
        for (int i = 0; i < points.size(); ++i) {
            a = points.get(i);
            b = points.get((i + 1) % points.size());
            if (a.getY() == b.getY()) {
                continue;
            }
            pMax = OurPoint.getMax(a, b);
            pMin = OurPoint.getMin(a, b);
            int ind = Math.min(pMin.getY(), pMax.getY());
            this.minY = Math.min(minY, Math.min(a.getY(), b.getY()));
            this.maxY = Math.max(maxY, Math.max(a.getY(), b.getY()));
            this.addEdge(ind, new OurNode(pMax.getY(), pMin.getX(), (float) 1.0 / getM(a, b)));
        }
        this.sort();
    }

    public final void sort() {
        Set<Integer> keys = this.edgeTable.keySet();
        for (Integer k : keys) {
            Collections.sort(this.edgeTable.get(k));
        }
    }

    public void addEdge(int ind, OurNode node) {
        if (!edgeTable.containsKey(ind)) {
            this.edgeTable.put(ind, new ArrayList<OurNode>());
        }
        this.edgeTable.get(ind).add(node);
    }

    public static float getM(OurPoint a, OurPoint b) {
        if (a.getX() == b.getX()) {
            return Float.MAX_VALUE;
        }
        return (a.getY() - b.getY()) / (float) (a.getX() - b.getX());
    }

    public void printMyPolygon() {
        for (Integer k : this.edgeTable.keySet()) {
            Collections.sort(this.edgeTable.get(k));
            System.out.print(k + " => ");
            for (int i = 0; i < this.edgeTable.get(k).size(); i++) {
                System.out.print(this.edgeTable.get(k).get(i).toString() + "" + (i < this.edgeTable.get(k).size() - 1 ? " ---> " : ""));
            }
            System.out.println();
        }
    }
}
